package com.mjk.common.tools.gson;

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.mjk.common.tools.gson.adapter.BeeGsonAdapterType;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.ObjectUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.XML;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class GsonUtils {
	private static final Gson gson;

	private static final Gson nullGson;
	static {
		gson = BeeGsonAdapterType.getGson(false);
		nullGson = BeeGsonAdapterType.getGson(true);
	}

	private GsonUtils(){}
	/**
	 * Gson格式字符串转换成实体类
	 * 
	 * @return T
	 */
	public static <T> T json2Bean(String jsonStr, Class<T> clazz) {
		try {
			if (ObjectUtils.isNotEmpty(jsonStr)) {
				return gson.fromJson(jsonStr, clazz);
			}
		} catch (JsonSyntaxException e) {
			BizLogger.error("转换JSON发生语法异常：{}", e);
		}
		return null;
	}

	/**
	 * 实体类转换成Gson格式字符串
	 * 
	 * @return String
	 */ 
	public static String bean2Json(Object obj) {
		if(ObjectUtils.isEmpty(obj)) {
			return "";
		}
		String json = bean2Json(obj, false);
		if(null == json) {
			return null;
		}
		if(ObjectUtils.isNotEmpty(json)&&json.contains("$cglib_prop_")){
			json = json.replace("$cglib_prop_", "");
		}
		return json;
	}

	/**
	 * 实体类转为GSON ，null字段为 \"\"
	 *
     */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static String bean2Json(Object obj, boolean havingNull) {
		try {
			if (null != obj) {
				if (havingNull) {
					if (obj instanceof Map map) {
						return nullGson.toJson(map);
					}
					if (obj instanceof List list) {
						List nullList = new ArrayList();
						for (Object o : list) {
							if (o instanceof Map map) {
								nullList.add(map);
							} else {
								return nullGson.toJson(obj);
							}
						}
						return nullGson.toJson(nullList);
					}
					return nullGson.toJson(obj);
				} else {
					return gson.toJson(obj);
				}
			}
		} catch (Exception e) {
			BizLogger.error("转换JSON发生语法异常：{}", e);
		}
		return null;
	}


	/**
	 * Gson格式字符串转换成MAP
	 * 
	 * @return Map
	 */
	@SuppressWarnings("rawtypes")
	public static Map json2Map(String jsonStr) {
		return gson.fromJson(jsonStr, Map.class);
	}

	/**
	 * long和float为0的转0，与json2Map不同的是为0.0
	 * 
	 * @return Map<String,String>
	 */
	public static Map<String, String> gson2Map(String jsonStr) {
		Map<String, String> map;
		try {
			map = gson.fromJson(jsonStr, new TypeToken<Map<String, String>>() {
			}.getType());
		} catch (Exception e) {
			map = json2Map(jsonStr);
		}
		return map;
	}

	/**
	 * 将json格式转换成list对象
	 *
     */
	public static <T> List<T> json2List(String jsonStr) {
		Type type = new TypeToken<List<T>>() {}.getType();
		return  gson.fromJson(jsonStr, type);
	}

	public static <T> List<T> json2List(String json,Class<T> clazz) {
        Type type = new ParameterizedTypeImpl(clazz);
        return  gson.fromJson(json, type);
    }
	/**
	 * 判断字符串是否是否是json格式字符串
	 * 
	 * @return boolean
	 */
	public static boolean isJson(String jsonStr) {
		if (ObjectUtils.isEmpty(jsonStr))
			return false;
		try {
			JsonElement jsonElement = JsonParser.parseString(jsonStr);
			return jsonElement.isJsonObject();
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 判断字符串是否是否是json格式字符串
	 * 
	 * @return boolean
	 */
	public static boolean isJsonArr(String jsonStr) {
		if (ObjectUtils.isEmpty(jsonStr))
			return false;
		try {
			JsonElement jsonElement =  JsonParser.parseString(jsonStr);
			return jsonElement.isJsonArray();
		} catch (Exception e) {
			return false;
		}
	}

	/**
     * json字符串转换成xml格式字符串
     */
    public static String json2Xml(String json){
    	String xml;
    	try{
    		JSONObject jsonObject = new JSONObject(json);
    		xml = XML.toString(jsonObject);
    	}catch(Exception e){
    		JSONArray jsonArray = new JSONArray(json);
    		xml =  XML.toString(jsonArray);
    	}
        return xml;
    }

    /**
     * xml字符串转换为json字符串
     */
    public static String xml2Json(String xml){
        JSONObject json = XML.toJSONObject(xml);
        return json.toString();
    }

	/**
	 * 替换JSON中的key
	 *
	 * @param json
	 * @param rep
	 * @return
	 */
	public static String replaceKey(String json, Map<String, String> rep) {
		if (json == null || json.isEmpty()) {
			return "";
		}
		JsonElement source = JsonParser.parseString(json);
		return replaceKey(source, rep).toString();
	}

	/**
	 * 替换json中某些键的值
	 *
	 * @param source
	 * @param rep
	 * @return
	 */
	public static JsonElement replaceKey(JsonElement source, Map<String, String> rep) {
        if (source == null || source.isJsonNull()) {  
            return JsonNull.INSTANCE;  
        }  
        if (source.isJsonPrimitive()) {  
            return source;  
        }  
        if (source.isJsonArray()) {  
            JsonArray jsonArr = source.getAsJsonArray();  
            JsonArray jsonArray = new JsonArray();  
            jsonArr.forEach(item -> jsonArray.add(replaceKey(item, rep)));
            return jsonArray;  
        }  
        if (source.isJsonObject()) {  
            JsonObject jsonObj = source.getAsJsonObject();  
            Iterator<Entry<String, JsonElement>> iterator = jsonObj.entrySet().iterator();  
            JsonObject newJsonObj = new JsonObject();  
            iterator.forEachRemaining(item -> {  
                String key = item.getKey();  
                JsonElement value = item.getValue();  
                if (rep.containsKey(key)) {
					key = rep.get(key);
				}
				newJsonObj.add(key, replaceKey(value, rep));
            });  
            return newJsonObj;  
        }
		return JsonNull.INSTANCE;
	}

	/**
	 * 获取json中某个键的值 支持多层级查询
	 *
	 * @param json
	 * @param key
	 * @return
	 */
	public static String getValueFromJson(String json, String key) {
		if (json == null) {
			return "";
		}
		JsonElement source = JsonParser.parseString(json);
		if (source.isJsonArray()) {
			JsonArray jsonArray = source.getAsJsonArray();
			for (JsonElement obj : jsonArray) {
				String value = getValueFromJson(obj.toString(), key);
				if (!value.isEmpty()) {
					return value;
				}
			}
		}
		if (source.isJsonObject()) {
			JsonObject jsonObject = source.getAsJsonObject();
			Iterator<Entry<String, JsonElement>> iterator = jsonObject.entrySet().iterator();

			while (iterator.hasNext()) {
				Entry<String, JsonElement> item = iterator.next();
				if (item.getKey().equals(key)) {
					if (item.getValue().isJsonNull()) {
						return "";
					}
					return item.getValue().toString().replace("\"", "");
				} else {
					String value = getValueFromJson(item.getValue().toString(), key);
					if (!value.isEmpty()) {
						return value;
					}
				}
			}
		}
		return "";
	}

	/**
	 * 把json中的 null value 转为 空
	 *
	 * @param json
	 * @return
	 */
	public static String convertNullsToEmptyString(String json) {
		if (json == null || json.isEmpty()) {
			return json;
		}
		JsonElement jsonElement = JsonParser.parseString(json);
		convertNullsToEmptyString(jsonElement);
		return jsonElement.toString();
	}

	/**
	 * 把json中的 null value 转为 空
	 *
	 * @param jsonElement json字符串
	 * @return
	 */
	private static void convertNullsToEmptyString(JsonElement jsonElement) {
		if (jsonElement == null || jsonElement.isJsonNull()) {
			return;
		}
		if (jsonElement.isJsonObject()) {
			JsonObject jsonObject = jsonElement.getAsJsonObject();
			for (String key : jsonObject.keySet()) {
				JsonElement element = jsonObject.get(key);
				if (element.isJsonNull()) {
					jsonObject.addProperty(key, "");
				} else if (element.isJsonObject()) {
					convertNullsToEmptyString(element);
				}else if( element.isJsonArray()){
					for (JsonElement tmp : element.getAsJsonArray()) {
						convertNullsToEmptyString(tmp);
					}
				}
			}
		} else if (jsonElement.isJsonArray()) {
			JsonArray jsonArray = jsonElement.getAsJsonArray();
			for (JsonElement element : jsonArray) {
				convertNullsToEmptyString(element);
			}
		}
	}
}